module aru_ub_wrgen_req_cntr (
    input logic       clk,
    input logic       rst_n,
    input logic       ub_wr_req_lst,
    input logic       ub_wr_req_vld,
    input logic       ub_wr_rsp_vld,
          done_if.out u_done_if
);
    localparam CNTR_CNT = 4;
    logic [$clog2(CNTR_CNT)-1:0] req_idx;
    logic [$clog2(CNTR_CNT)-1:0] rsp_idx;
    logic [                 3:0] req_cntr [CNTR_CNT];
    logic                        recvd_lst[CNTR_CNT];

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            req_idx <= 'd0;
        end else if (ub_wr_req_vld && ub_wr_req_lst) begin
            req_idx <= req_idx + 'd1;
        end
    end

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (integer i = 0; i < CNTR_CNT; i = i + 1) begin
                recvd_lst[i] <= 'd0;
            end
        end else begin
            for (integer i = 0; i < CNTR_CNT; i = i + 1) begin
                if (ub_wr_req_vld && ub_wr_req_lst && (i == req_idx)) begin
                    recvd_lst[i] <= 1'b1;
                end else if (req_cntr[i] == 'd1 && ub_wr_rsp_vld && recvd_lst[i] && (i == rsp_idx)) begin
                    recvd_lst[i] <= 1'b0;
                end
            end
        end
    end

    logic cntr_inc[CNTR_CNT];
    logic cntr_dec[CNTR_CNT];
    always_comb begin
        for (integer i = 0; i < CNTR_CNT; i = i + 1) begin
            cntr_inc[i] = ub_wr_req_vld && (i == req_idx);
            cntr_dec[i] = ub_wr_rsp_vld && (i == rsp_idx);
        end
    end

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            for (integer i = 0; i < CNTR_CNT; i = i + 1) begin
                req_cntr[i] <= 'd0;
            end
        end else begin
            for (integer i = 0; i < CNTR_CNT; i = i + 1) begin
                case ({
                    cntr_inc[i], cntr_dec[i]
                })
                    2'b10:   req_cntr[i] <= req_cntr[i] + 'd1;
                    2'b01:   req_cntr[i] <= req_cntr[i] - 'd1;
                    default: req_cntr[i] <= req_cntr[i];
                endcase
            end
        end
    end

    always_ff @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rsp_idx <= 'd0;
        end else if (req_cntr[rsp_idx] == 'd1 && ub_wr_rsp_vld && recvd_lst[rsp_idx]) begin
            rsp_idx <= rsp_idx + 'd1;
        end
    end
    assign u_done_if.vld = req_cntr[rsp_idx] == 'd1 && ub_wr_rsp_vld && recvd_lst[rsp_idx];

endmodule
